package com.zzh.tools.hook;

import android.annotation.SuppressLint;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author zhangzhihao
 * @email zhangzhihao@gongjiangren.net
 * @date 2020-09-21
 * @desc
 */
public class HookClickListener {

    public static class HookOnClickListener implements View.OnClickListener {

        private View.OnClickListener onClickListener;

        public HookOnClickListener(View.OnClickListener onClickListener) {
            this.onClickListener = onClickListener;
        }

        @Override
        public void onClick(View v) {
            Log.i("zhangzhihao", "这里是hook操作的拦截");
            // 处理埋点等其他操作
            onClickListener.onClick(v);
        }
    }

    /**
     * 进行点击事件hook处理
     *
     * @param view
     */
    public static void hookOnClickListener(View view) {
        if (view == null) {
            return;
        }
        try {
            Class viewClazz = Class.forName("android.view.View");
            //事件监听器都是这个实例保存的
            Method listenerInfoMethod = viewClazz.getDeclaredMethod("getListenerInfo");
            if (!listenerInfoMethod.isAccessible()) {
                listenerInfoMethod.setAccessible(true);
            }
            Object listenerInfoObj = listenerInfoMethod.invoke(view);

            @SuppressLint("PrivateApi")
            Class listenerInfoClazz = Class.forName("android.view.View$ListenerInfo");

            Field onClickListenerField = listenerInfoClazz.getDeclaredField("mOnClickListener");
            //修改修饰符带来不能访问的问题
            if (!onClickListenerField.isAccessible()) {
                onClickListenerField.setAccessible(true);
            }
            Object clickObject = onClickListenerField.get(listenerInfoObj);
            if (clickObject != null) {
                //更换成自己的点击事件
                onClickListenerField.set(listenerInfoObj, new HookOnClickListener((View.OnClickListener) clickObject));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 进行点击事件hook处理
     *
     * @param rootView
     */
    public static void hooksOnClickListener(View rootView) {
        if (rootView == null) {
            return;
        }
        if (rootView instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) rootView;
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                hooksOnClickListener(viewGroup.getChildAt(i));
            }
        } else {
            hookOnClickListener(rootView);
        }
    }

}
